import { Entity } from "../../../../../Core/Module/Entity/Entity";
import { EventSystem } from "../../../../../Core/Module/EventSystem/EventSystem";
import { IAwake } from "../../../../../Core/Module/EventSystem/IAwakeSystem";
import { ITransfer } from "../../../../../Core/Module/EventSystem/ITransfer";
import { ComponentOf, ExpandOf, ImplementsInterface } from "../../../../../Decorator/Decorator";
import { Dictionary } from "../../../../../Support/Share/Lib/Dictionary";
import { Unit } from "../Unit/Unit";
import { NumericType } from "./NumericType";

export module EventType {
    export class NumbericChange {
        public Unit: Unit;
        public NumericType: number;
        public Old: number;
        public New: number;
    }
}

@ComponentOf(Unit)
@ImplementsInterface(IAwake)
@ImplementsInterface(ITransfer)
export class NumericComponent extends Entity implements IAwake, ITransfer {

    public NumericDic: Dictionary<number, number> = new Dictionary<number, number>();

}

/**
 * 使用 Expand 扩展方法
 * 
 * 必须作出以下申明，才能调用对象的扩展方法
 */
declare module "./NumericComponent" {

    interface NumericComponent {
        GetAsFloat(numericType: number): number;
        GetAsInt(numericType: number): number;
        GetAsLong(numericType: number): number;
        Set(nt: number, value: number);
        SetNoEvent(numericType: number, value: number): void;
        Insert(numericType: number, value: number, isPublicEvent: boolean): void;
        GetByKey(key: number);
        Update(numericType: number, isPublicEvent: boolean): void;
    }

}

@ExpandOf(NumericComponent)
export class NumericComponentSystem {

    private static GetAsFloat(self: NumericComponent, numericType: number): number {
        return self.GetByKey(numericType) / 10000;
    }

    private static GetAsInt(self: NumericComponent, numericType: number): number {
        return self.GetByKey(numericType);
    }

    private static GetAsLong(self: NumericComponent, numericType: number): number {
        return self.GetByKey(numericType);
    }

    private static Set(self: NumericComponent, nt: number, value: number) {
        self[nt] = value;
    }

    private static SetNoEvent(self: NumericComponent, numericType: number, value: number): void {
        self.Insert(numericType, value, false);
    }

    private static Insert(self: NumericComponent, numericType: number, value: number, isPublicEvent: boolean = true): void {
        const oldValue = self.GetByKey(numericType);
        if (oldValue == value) {
            return;
        }

        self.NumericDic[numericType] = value;

        if (numericType >= NumericType.Max) {
            self.Update(numericType, isPublicEvent);
            return;
        }

        if (isPublicEvent) {
            let numbericChange = new EventType.NumbericChange();
            {
                numbericChange.Unit = self.GetParent<Unit>();
                numbericChange.New = value;
                numbericChange.Old = oldValue;
                numbericChange.NumericType = numericType;
            }
            EventSystem.Instance.Publish(self.DomainScene(), numbericChange);
        }
    }

    private static GetByKey(self: NumericComponent, key: number) {
        let value = self.NumericDic.TryGetValue(key);
        return value;
    }

    private static Update(self: NumericComponent, numericType: number, isPublicEvent: boolean): void {
        let final = numericType / 10;
        let bas = final * 10 + 1;
        let add = final * 10 + 2;
        let pct = final * 10 + 3;
        let finalAdd = final * 10 + 4;
        let finalPct = final * 10 + 5;

        // 一个数值可能会多种情况影响，比如速度,加个buff可能增加速度绝对值100，也有些buff增加10%速度，所以一个值可以由5个值进行控制其最终结果
        // final = (((base + add) * (100 + pct) / 100) + finalAdd) * (100 + finalPct) / 100;
        let result = (((self.GetByKey(bas) + self.GetByKey(add)) * (100 + self.GetAsFloat(pct)) / 100 + self.GetByKey(finalAdd)) * (100 + self.GetAsFloat(finalPct)) / 100);
        self.Insert(final, result, isPublicEvent);
    }

}
